﻿using System;
using UnityEngine;

namespace Gj
{
    public class HexMetrics
    {
        public const float outerToInner = 0.866025404f;
        public const float innerToOuter = 1f / outerToInner;
        public static HexMetrics Default;

        private float _innerDiameter;

        private float _innerRadius;

        private HexMode _mode;

        private HexOffset _offset;

        public Func<HexCube, Vector2Int> CubeToOffset;

        public Func<Vector2Int, HexCube> OffsetToCube;
        public HexOrientation orientation;
        public Vector2 origin = new(0, 0);
        public Vector2 size;
        public Vector2[] positionVERTEX;

        public int wrapSize;

        static HexMetrics()
        {
            Default = new HexMetrics(0.5f, 0.5f, HexMode.Row, HexOffset.EVEN);
        }

        public HexMetrics(float width, float height, HexMode mode, HexOffset offset)
        {
            size = new Vector2(width, height);
            OuterRadius = width;
            Mode = mode;
            Offset = offset;
            Update();
            var xC = OffsetToCube(new Vector2Int(1, 0)).ToPosition();
            var yC = OffsetToCube(new Vector2Int(0, 1)).ToPosition();
            // Debug.LogError(xC+""+yC);
            positionVERTEX = new Vector2[6];
            for (var i = 0; i < 6; i++)
            {
                positionVERTEX[i] = new Vector2(HexDirectionExtensions.VERTEX[i].x * xC.x, HexDirectionExtensions.VERTEX[i].y * yC.z);
            }
        }

        public HexOffset Offset
        {
            get => _offset;
            set
            {
                _offset = value;
                switch (_offset)
                {
                    case HexOffset.ODD:
                        break;
                    case HexOffset.EVEN:
                        break;
                }

                Update();
            }
        }

        public HexMode Mode
        {
            get => _mode;
            set
            {
                _mode = value;
                switch (_mode)
                {
                    case HexMode.Column:
                        orientation = HexOrientation.LayoutPointy;
                        break;
                    case HexMode.Row:
                        orientation = HexOrientation.LayoutFlat;
                        break;
                }

                Update();
            }
        }

        public float OuterRadius { get; }

        public float InnerRadius
        {
            get
            {
                if (_innerRadius == 0f) _innerRadius = OuterRadius * outerToInner;

                return _innerRadius;
            }
        }

        public float InnerDiameter
        {
            get
            {
                if (_innerDiameter == 0f) _innerDiameter = InnerRadius * 2f;

                return _innerDiameter;
            }
        }

        public bool Wrapping => wrapSize > 0;

        private void Update()
        {
            if (_mode == HexMode.Column)
                switch (_offset)
                {
                    case HexOffset.ODD:
                        OffsetToCube = p => HexCube.OddRToCube(p, this);
                        CubeToOffset = HexCube.ToOddR;
                        break;
                    case HexOffset.EVEN:
                        OffsetToCube = p => HexCube.EvenRToCube(p, this);
                        CubeToOffset = HexCube.ToEvenR;
                        break;
                }
            else
                switch (_offset)
                {
                    case HexOffset.ODD:
                        OffsetToCube = p => HexCube.OddQToCube(p, this);
                        CubeToOffset = HexCube.ToOddQ;
                        break;
                    case HexOffset.EVEN:
                        OffsetToCube = p => HexCube.EvenQToCube(p, this);
                        CubeToOffset = HexCube.ToEventQ;
                        break;
                }
        }
    }
}